<template>
  <div
    class="end-node-shape basic-node"
    ref="NodeRef"
    :id="getNode().id"
    :class="{ 'node-click': nodeActiveStatusObject[getNode().id] }"
    @click="clearQuillSelect"
  >
    <BasicNodeTop ref="BasicNodeTopRef"/>
    <div v-if="!nodeDta.isNodeFold">
      <el-form ref="RuleFormRef" :model="nodeDta" label-width="100" label-position="left">
        <el-form-item label="选择回答模式">
          <el-select
            style="flex: 1"
            v-model="nodeDta.type"
            placeholder="请选择回答模式"
            @change="typeChange($event)"
          >
            <el-option
              v-for="item in AnswerModeList"
              :key="item.value"
              :label="item.name"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <BasicInputForm ref="BasicInputFormForm" title="输出" class="mr-b-8"/>
        <div class="basic-input-form pa-b-1 mr-b-8" v-show="nodeDta.type === EndNodeType.STREAM">
          <div class="pa-b-12 flex-space">
            <div>
              <span>
                <el-link
                  :underline="false"
                  class="link-btn"
                  @click="nodeDta.isOutFold = !nodeDta.isOutFold"
                >
                  <el-icon v-show="!nodeDta.isOutFold"><ArrowDown /></el-icon>
                  <el-icon v-show="nodeDta.isOutFold"><ArrowRight /></el-icon>
                </el-link>
              </span>
              <span>回答内容</span>
            </div>
            <el-form-item label="流式输出" class="stream" label-width="70">
              <template #label>
                流式输出
                <el-tooltip
                  effect="dark"
                  content="开启时，回复内容中的大语言模型的生成内容将会注字流式输出；关闭时，回复内容将全部生成后一次性输出。"
                  placement="top"
                >
                  <el-icon><InfoFilled /></el-icon>
                </el-tooltip>
              </template>
              <el-switch
                v-model="nodeDta.stream"
              />
            </el-form-item>
          </div>
          <el-form-item
            class="prompt-item"
            label-width="0"
            v-show="!nodeDta.isOutFold"
            prop="reply"
            :rules="[
              {
                required: nodeDta.type === EndNodeType.STREAM,
                message: '请输入output',
                trigger: 'change'
              }
            ]"
            @mousemove.stop
          >
            <QuillEdit
              message="{{output}}"
              ref="QuillEditRef"
              :elementId="nanoId()"
              :keyId="1"
              :input_variables="nodeDta.out_variables"
              @textChange="orderTextChange"
            />
          </el-form-item>
        </div>
      </el-form>
    </div>
  </div>
</template>

<script setup lang="ts" name="EndNodeShape">
import {computed, inject, nextTick, onMounted, ref, watch} from 'vue';
import {GenerationNodeData} from '@/view/graph/methods/methods';
import {NODES_MAP} from '@/view/graph/model/nodes';
import {AnswerModeList, EndNode, EndNodeType, nanoId, NodeTile} from '@/view/graph/model/type';
import {storeToRefs} from 'pinia';
import {workFlowStoreCounter} from '@/store/work-flow';
import QuillEdit from "@/view/graph/component/custom-node-shape/quill-edit/quill-edit.vue";
import BasicInputForm from "@/view/graph/component/custom-node-shape/basic-input-form/basic-input-form.vue";

const getNode = inject('getNode') as () => any;

const workFlowStore = workFlowStoreCounter();
const { nodeActiveStatusObject } = storeToRefs(workFlowStore);

const nodeForm = GenerationNodeData({ code: NODES_MAP.END, name: '结束' }) as EndNode & NodeTile;
const nodeDta = ref<EndNode & NodeTile>({
  ...nodeForm
});

const BasicInputFormForm = ref();
const NodeRef = ref(null);
const QuillEditRef = ref();
const RuleFormRef = ref();
const BasicNodeTopRef = ref();

const isNodeFold = computed(() => {
  return nodeDta.value.isNodeFold;
});


watch(isNodeFold, newValue => {
  nextTick(() => {
    if (!newValue) {
      QuillEditRef.value.init(nodeDta.value.reply, nodeDta.value.out_variables);
    }
  });
});

watch(
    nodeDta,
    newValue => {
      getNode().setData(
          {
            ...getNode().getData(),
            ...newValue,
            lastModify: new Date()
          },
          { overwrite: true }
      );
      if (!newValue.isNodeFold) {
        nextTick(() => {
          BasicInputFormForm.value.init({
            isInputFold: newValue.isInputFold,
            input_variables: newValue.out_variables
          });
        });
      }
    },
    {
      deep: true
    }
);

/**
 * 监听节点宽高变化
 */
const handleResize = (entries: any) => {
  for (let entry of entries) {
    const { scrollWidth, scrollHeight } = entry.target;
    getNode().size(scrollWidth, scrollHeight);
  }
};

onMounted(() => {
  nodeDta.value = getNode().getData();
  nodeDta.value.submitFormFunction = submitForm;
  nextTick(() => {
    const observer = new ResizeObserver(handleResize);
    if (NodeRef.value) {
      observer.observe(NodeRef.value);
    }
    nextTick(() => {
      if (!nodeDta.value.isNodeFold) {
        QuillEditRef.value.init(nodeDta.value.reply, nodeDta.value.out_variables);
      }
    });
  });
});

/**
 * 更新order并触发校验
 */
function orderTextChange(text: string) {
  if (!nodeDta.value.isWatch && nodeDta.value.reply !== text && text) {
    nodeDta.value.isWatch = true;
  }
  nodeDta.value.reply = text;
  if (nodeDta.value.type === EndNodeType.STREAM) {
    RuleFormRef.value?.validateField('reply');
  }
}

/**
 * 去除提示窗
 */
function clearQuillSelect() {
  if (QuillEditRef.value) {
    QuillEditRef.value.showSelect = false;
  }
}

/**
 * form表单校验
 */
const submitForm = async (): Promise<boolean> => {
  if (!RuleFormRef.value) {
return false;
}
  return new Promise<boolean>(resolve => {
    RuleFormRef.value.validate(async (valid: boolean) => {
      const isInput = await BasicInputFormForm.value.submitForm();
      const isNodeTitle = await BasicNodeTopRef.value.submitForm();
      resolve(valid && isInput && isNodeTitle);
    });
  });
};

/**
 * type切换
 * @param val
 */
function typeChange(val: number) {
  nodeDta.value.type = val;
}
</script>

<style scoped lang="scss">
.end-node-shape {
  width: 538px;
}
</style>
